from django.contrib.auth.models import Permission, Group
from rest_framework import serializers
from rest_framework.validators import UniqueValidator

from .models import Category, Product, ProductImage, Banner, SpecialOffer, SKU, SalesOrder, UserInfo, OrderItem, LogisticsInfo

from django.core.exceptions import SuspiciousOperation

from django.core.validators import URLValidator
from django.utils.deconstruct import deconstructible


class SKUSerializer(serializers.ModelSerializer):  # SKU
    image = serializers.SerializerMethodField()

    class Meta:
        model = SKU
        exclude = ['product']  # 直接排除指定字段
        # 此时不再需要 fields = '__all__'
        # 或指定字段：fields = ['id', 'color', 'size', 'price', ...]
        depth = 1  # 可选，展示外键关联对象的完整结构

    def get_image(self, obj):
        request = self.context.get('request')
        if obj.image:
            return request.build_absolute_uri(obj.image.url)
        return None


class ProductImageSerializer(serializers.ModelSerializer):  # 商品主图多张上传
    class Meta:
        model = ProductImage
        fields = ['image']


class ProductSerializer(serializers.ModelSerializer):  # 商品Product
    # main_image = serializers.SerializerMethodField()
    main_images = ProductImageSerializer(many=True, required=False)
    video_url = serializers.SerializerMethodField()
    thumbnail = serializers.SerializerMethodField()
    category = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
    description = serializers.SerializerMethodField()  # 自定义富文本字段(商品描述)

    # 核心嵌套字段
    skus = SKUSerializer(
        # source='skus',  # 使用自动生成的反向关联管理器
        many=True,
        read_only=True
    )
    # 附加统计字段（可选）
    sku_count = serializers.SerializerMethodField()

    class Meta:
        model = Product
        # fields = [
        #     'id', 'name', 'main_images', 'category', 'video_url', 'thumbnail',
        #     'stock', 'price', 'original_price', 'sales_total', 'details',
        #     'description', 'is_active', 'created_at', 'skus', 'sku_count']
        fields = "__all__"
        read_only_fields = ['created_at', 'sales_total']

    def validate_price(self, value):
        if value <= 0:
            raise serializers.ValidationError("价格必须大于0")
        return value

    def get_main_images(self, obj):
        request = self.context.get('request')
        if obj.main_image:
            return request.build_absolute_uri(obj.main_image.url)
        return None

    def get_video_url(self, obj):
        request = self.context.get('request')
        if obj.video_url:
            return request.build_absolute_uri(obj.video_url.url)
        return None

    def get_thumbnail(self, obj):
        request = self.context.get('request')
        if obj.thumbnail:
            return request.build_absolute_uri(obj.thumbnail.url)
        return None

    def get_sku_count(self, obj):
        """自动计算关联SKU数量"""
        return obj.skus.count()

    def get_description(self, obj):
        # 自动补全媒体文件完整URL
        from django.urls import reverse
        from django.conf import settings

        # 正则替换相对路径为绝对路径
        import re
        desc = re.sub(
            r'src="/media/(.*?)"',
            rf'src="{settings.WECHAT_NOTIFY_URL}/media/\g<1>"',
            obj.description
        )
        return desc

    def create(self, validated_data):
        images_data = validated_data.pop('main_images', [])
        product = Product.objects.create(**validated_data)
        for image_data in images_data:
            ProductImage.objects.create(product=product, **image_data)
        return product


class BannerSerializer(serializers.ModelSerializer):  # 轮播图
    image = serializers.SerializerMethodField()
    product = serializers.PrimaryKeyRelatedField(read_only=True)

    class Meta:
        model = Banner
        fields = [
            'id', 'title', 'image', 'link', 'order',
            'is_active', 'start_time', 'product'
        ]
        extra_kwargs = {
            'link': {'required': False},
            'product': {'required': False},
            'start_time': {'format': '%Y-%m-%d %H:%M:%S'}  # 时间格式配置
        }

    def get_image(self, obj):
        request = self.context.get('request')
        if obj.image:
            return request.build_absolute_uri(obj.image.url)
        return None


class SpecialOfferSerializer(serializers.ModelSerializer):  # 特价商品
    promo_image = serializers.SerializerMethodField()
    product_name = serializers.SerializerMethodField()

    class Meta:
        model = SpecialOffer
        fields = '__all__'
        # fields = [
        #     'id', 'promo_type', 'product', 'start_time', 'end_time',
        #     'discount_rate', 'is_active', 'created_at'
        # ]
        extra_kwargs = {
            'product': {'required': True},
            # 'discount_rate': {'decimal_places': 2}
        }

    def to_representation(self, instance):
        data = super().to_representation(instance)
        # 将促销类型转换为可读标签
        data['promo_type'] = instance.get_promo_type_display()
        return data

    def get_promo_image(self, obj):
        request = self.context.get('request')
        if obj.promo_image:
            return request.build_absolute_uri(obj.promo_image.url)
        return None

    def get_product_name(self, obj):
        # obj.product.title: product是关联的外键字段
        return obj.product.name if obj.product else None


# ################# 以下为分类 ##########################
class CategorySerializer(serializers.ModelSerializer):
    # image = serializers.SerializerMethodField()

    class Meta:
        model = Category
        fields = ['id', 'name']  # , 'image'

    # def get_image(self, obj):
    #     request = self.context.get('request')
    #     return request.build_absolute_uri(obj.image.url) if obj.image else None


class CategoryWithProductsSerializer(CategorySerializer):
    products = serializers.SerializerMethodField()

    class Meta(CategorySerializer.Meta):
        fields = CategorySerializer.Meta.fields + ['products']

    def get_products(self, obj):
        """分页处理后的商品数据"""
        request = self.context.get('request')
        products = obj.products.filter(is_active=True)
        page = self.paginator.paginate_queryset(products, request)
        serializer = ProductSerializer(page, many=True, context={'request': request})
        return {
            'count': self.paginator.page.paginator.count,
            'next': self.paginator.get_next_link(),
            'previous': self.paginator.get_previous_link(),
            'results': serializer.data
        }


# ########################### 以下序列化下单支付有关数据 #########################
class AddressSerializer(serializers.Serializer):
    id = serializers.CharField()
    userName = serializers.CharField()
    telNumber = serializers.CharField()
    province = serializers.CharField()
    city = serializers.CharField()
    county = serializers.CharField()
    detail = serializers.CharField()
    isDefault = serializers.BooleanField()


class GoodsSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    image = serializers.URLField()
    attributes_hash = serializers.CharField()
    attributes_json = serializers.CharField()  # 或者使用JSONField如果DRF支持
    price = serializers.DecimalField(max_digits=10, decimal_places=2)
    original_price = serializers.DecimalField(max_digits=10, decimal_places=2)
    stock = serializers.IntegerField()
    is_active = serializers.BooleanField()
    created_at = serializers.DateTimeField()
    title = serializers.CharField()
    count = serializers.IntegerField()


class OrderDataSerializer(serializers.Serializer):
    address = AddressSerializer()  # 嵌套Address
    goods = GoodsSerializer(many=True)  # 嵌套Goods列表
    total = serializers.DecimalField(max_digits=10, decimal_places=2)
    payment = serializers.CharField()
    mobile = serializers.CharField()


class OrderInfoSerializer(serializers.Serializer):
    orderData = OrderDataSerializer()


class OrderStatusSerializer(serializers.ModelSerializer):
    class Meta:
        model = SalesOrder
        fields = ['order_no', 'status', 'payment_time']


# ################# 用户序列化器: #################################
class UserInfoSerializer(serializers.ModelSerializer):
    # 如果不考虑后续下载等，直接：
    # avatar = serializers.CharField()  # 允许任意字符串格式
    avatar = serializers.ImageField(
        required=False,
        allow_null=True,
        # 处理文件名冲突
        validators=[UniqueValidator(queryset=UserInfo.objects.all(), lookup='iexact')]
    )
    nickname = serializers.CharField(allow_null=True)

    class Meta:
        model = UserInfo
        fields = ['id', 'avatar', 'nickname', 'username', 'phone', 'groups']
        extra_kwargs = {
            'avatar': {'required': False},
            'nickname': {'required': False}
        }

    def update(self, instance, validated_data):
        old_avatar = instance.avatar
        try:
            if 'avatar' in validated_data:
                if old_avatar:
                    try:
                        old_avatar.delete(save=False)
                    except Exception as e:
                        raise SuspiciousOperation(f"旧头像删除失败: {str(e)}")
                # 提取新头像文件并从 validated_data 中移除，避免父类重复处理
                new_avatar = validated_data.pop('avatar', None)
                # 手动将新文件赋值给模型字段，触发 Django 自动保存逻辑
                if new_avatar:
                    instance.avatar = new_avatar
        except Exception as e:
            # 回滚：清除已上传但未关联到数据库的文件
            if 'avatar' in validated_data:
                instance.avatar.delete(save=False)
            raise e
        return super().update(instance, validated_data)


class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = UserInfo
        fields = ['id', 'username', 'email', 'phone', 'is_active', 'date_joined']
        extra_kwargs = {
            'password': {'write_only': True}
        }


class UserCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserInfo
        fields = ['username', 'password', 'email', 'phone']


# ##############  获取订单信息 #######################
class OrderItemSerializer(serializers.ModelSerializer):
    sku_name = serializers.CharField(source='sku.name', read_only=True)
    sku_info = serializers.SerializerMethodField()

    class Meta:
        model = OrderItem
        # fields = ['sku', 'sku_name', 'quantity', 'unit_price', 'total_price']
        fields = '__all__'
        read_only_fields = ['unit_price', 'total_price']

    def get_sku_info(self, obj):
        if obj.sku:
            request = self.context.get('request')  # 获取 request 对象，需views传递过来
            image_url = obj.sku.image.url if obj.sku.image else None
            if image_url and request:  # 确保 request 存在
                image_url = request.build_absolute_uri(image_url)
            return {
                'title': obj.sku.product.name,
                'attributes_json': obj.sku.attributes_json,
                'price': obj.sku.price,
                'original_price': obj.sku.original_price,
                'stock': obj.sku.stock,
                'image': image_url,  # 图片需要特殊处理一下：和返回绝对路径
            }
        return None


class SalesOrderSerializer(serializers.ModelSerializer):
    items = OrderItemSerializer(many=True, read_only=True)
    created_at = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")  # 定义格式化字段
    payment_time = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S")  # 定义格式化字段

    address_info = serializers.SerializerMethodField()

    class Meta:
        model = SalesOrder
        fields = [
            'order_no', 'total_amount', 'status',
            'created_at', 'payment_time', 'items',
            'address_info', 'transaction_id'
        ]

    def get_address_info(self, obj):
        if obj.address:
            return {
                'receiver': obj.address.receiver,
                'mobile': obj.address.mobile,
                'full_address': obj.address.province + ' ' +
                                obj.address.city + ' ' +
                                obj.address.district + ' ' +
                                obj.address.detail
            }
        return None


# #############  物流信息跟踪  #################
class LogisticsSerializer(serializers.ModelSerializer):
    traces = serializers.SerializerMethodField()
    company = serializers.CharField(source='get_company_display')

    class Meta:
        model = LogisticsInfo
        fields = ['tracking_number', 'company', 'traces']

    def get_traces(self, obj):
        return [{
            'time': t['time'],
            'status': t['status'],
            'location': t['location'],
            'lat': t['lat'],
            'lng': t['lng']
        } for t in obj.raw_data.get('traces', [])]


# #################### 用户认证权限管理需要 #########################
# serializers.py
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer


class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)
        token['is_staff'] = user.is_staff
        token['permissions'] = list(user.get_all_permissions())
        return token


class GroupDetailSerializer(serializers.ModelSerializer):
    permissions = serializers.SlugRelatedField(
        many=True,
        slug_field='codename',
        queryset=Permission.objects.all()
    )

    class Meta:
        model = Group
        fields = ('id', 'name', 'permissions')
        depth = 1


class UserInfoDetailSerializer(UserInfoSerializer):
    groups = GroupDetailSerializer(many=True, read_only=True)
    user_permissions = serializers.SlugRelatedField(
        many=True,
        slug_field='codename',
        read_only=True
    )

    class Meta(UserInfoSerializer.Meta):
        fields = UserInfoSerializer.Meta.fields + ['is_staff', 'user_permissions']
